#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>
#include <string>
#include "LockGuard.hpp"
using namespace std;

// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //锁

// #define NUM 4
// int tickets = 1000; //用多线程，模拟一轮抢票

// class threadData
// {
// public:
//     threadData(int number)
//     {
//         _threadname = "thread-" + to_string(number);
//     }
// public:
//     string _threadname;
// };
// void* getTicket(void* args)
// {
//     threadData *td = static_cast<threadData*>(args);
    
//     const char* name = td->_threadname.c_str();
//     while(true)
//     {
//         //专门开出来一个代码块，让usleep不会再临界资源中
//         {
//             LockGuard lockguard(&lock); //临时的LockGuard对象, RAII风格的锁
//             if(tickets > 0)
//             {
//                 usleep(1000);
//                 printf("who = %s, get a ticket: %d\n", name, tickets);
//                 tickets--;
//             }
//             else
//             {
//                 break;
//             }
//         }
//         usleep(13); 
//     }
//     printf("%s ... quit\n", name);
//     return nullptr;
// }
// int main()
// {
//     vector<pthread_t> tids;
//     vector<threadData*> thread_datas;
//     for(int i = 0; i <= NUM; i++)
//     {
//         pthread_t tid;
//         threadData* td = new threadData(i);
//         thread_datas.push_back(td);
//         pthread_create(&tid, nullptr, getTicket, thread_datas[i]);
//         tids.push_back(tid);
//     }

//     for(auto thread : tids)
//     {
//         pthread_join(thread, nullptr);
//     }
//     for(auto td : thread_datas)
//     {
//         delete td;
//     }
//     return 0;
// }















pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //锁

#define NUM 4
int tickets = 1000; //用多线程，模拟一轮抢票

class threadData
{
public:
    threadData(int number/*, pthread_mutex_t* mutex*/)
    {
        _threadname = "thread-" + to_string(number);
        //_lock = mutex;
    }
public:
    string _threadname;
   // pthread_mutex_t* _lock;
};
void* getTicket(void* args)
{
    threadData *td = static_cast<threadData*>(args);
    
    const char* name = td->_threadname.c_str();
    while(true)
    {
        //pthread_mutex_lock(td->_lock); //申请锁成功，才能往后执行，不成功，阻塞等待
        pthread_mutex_lock(&lock); //申请锁成功，才能往后执行，不成功，阻塞等待
        pthread_mutex_lock(&lock); //申请锁成功，才能往后执行，不成功，阻塞等待
        if(tickets > 0)
        {
            usleep(1000);
            printf("who = %s, get a ticket: %d\n", name, tickets);
            tickets--;
            pthread_mutex_unlock(&lock);
            //pthread_mutex_unlock(td->_lock);
        }
        else
        {
            pthread_mutex_unlock(&lock);
            // pthread_mutex_unlock(td->_lock);
            break;
        }
        usleep(13); //有可能它一释放锁，就立马抢到了
    }
    printf("%s ... quit\n", name);
    return nullptr;
}
int main()
{
    //pthread_mutex_init(&lock, nullptr);
    
    vector<pthread_t> tids;
    vector<threadData*> thread_datas;
    for(int i = 0; i <= NUM; i++)
    {
        pthread_t tid;
        threadData* td = new threadData(i/*, &lock*/);
        thread_datas.push_back(td);
        pthread_create(&tid, nullptr, getTicket, thread_datas[i]);
        tids.push_back(tid);
    }

    for(auto thread : tids)
    {
        pthread_join(thread, nullptr);
    }
    for(auto td : thread_datas)
    {
        delete td;
    }
    //pthread_mutex_destroy(&lock);
    return 0;
}